﻿using JinYuan.ControlLib.UCHelper;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace JinYuan.ControlLib
{

    //public partial class UCRollText : UserControl
    //{

    //    /// <summary>
    //    /// The m intdirection
    //    /// </summary>
    //    int m_intdirection = 1;

    //    /// <summary>
    //    /// The rect text
    //    /// </summary>
    //    Rectangle rectText;
    //    /// <summary>
    //    /// The m timer
    //    /// </summary>
    //    System.Timers.Timer m_timer;

    //    /// <summary>
    //    /// The roll style
    //    /// </summary>
    //    private RollStyle _RollStyle = RollStyle.LeftToRight;

    //    /// <summary>
    //    /// 文本改变是否重新从边缘运动
    //    /// </summary>
    //    private bool _ISChangeReset = false;


    //    private readonly SemaphoreSlim _updateLock = new SemaphoreSlim(1, 1);
    //    private CancellationTokenSource _cts = new CancellationTokenSource();
    //    private volatile bool _isStop = true;
    //    private Rectangle _rectText;
    //    private int _moveDirection = 1;
    //    private const int DEFAULT_MOVE_STEP = 5;
    //    private const int DEFAULT_SLEEP_TIME = 200;

    //    #region Properties

    //    public override Font Font
    //    {
    //        get => base.Font;
    //        set
    //        {
    //            base.Font = value;
    //            UpdateTextRectangle();
    //        }
    //    }

    //    public override string Text
    //    {
    //        get => base.Text;
    //        set
    //        {
    //            base.Text = value;
    //            UpdateTextRectangle();
    //        }
    //    }

    //    private RollStyle _rollStyle = RollStyle.LeftToRight;
    //    public RollStyle RollStyle
    //    {
    //        get => _rollStyle;
    //        set
    //        {
    //            _rollStyle = value;
    //            _moveDirection = value == RollStyle.RightToLeft ? -1 : 1;
    //            ResetTextPosition();
    //        }
    //    }

    //    private bool _isChangeReset;
    //    [Description("文本改变是否重新从边缘运动"), Category("自定义")]
    //    public bool IsChangeReset
    //    {
    //        get => _isChangeReset;
    //        set => _isChangeReset = value;
    //    }

    //    private bool _isExit;
    //    [Description("是否退出"), Category("自定义")]
    //    public bool IsExit
    //    {
    //        get => _isExit;
    //        set
    //        {
    //            _isExit = value;
    //            if (value)
    //            {
    //                StopAnimation();
    //            }
    //        }
    //    }

    //    private int _moveSleepTime = DEFAULT_SLEEP_TIME;
    //    [Description("每次滚动间隔时间，越小速度越快"), Category("自定义")]
    //    public int MoveSleepTime
    //    {
    //        get => _moveSleepTime;
    //        set => _moveSleepTime = value > 0 ? value : DEFAULT_SLEEP_TIME;
    //    }

    //    #endregion

    //    public UCRollText()
    //    {
    //        InitializeControl();
    //        InitializeEvents();
    //        StartAnimation();
    //    }

    //    private void InitializeControl()
    //    {
    //        SetStyle(ControlStyles.AllPaintingInWmPaint |
    //                ControlStyles.DoubleBuffer |
    //                ControlStyles.ResizeRedraw |
    //                ControlStyles.Selectable |
    //                ControlStyles.SupportsTransparentBackColor |
    //                ControlStyles.UserPaint, true);

    //        Size = new Size(450, 30);
    //        Text = "滚动文字";
    //        ForeColor = Color.FromArgb(255, 77, 59);
    //    }

    //    private void InitializeEvents()
    //    {
    //        Load += UCRollText_Load;
    //        SizeChanged += UCRollText_SizeChanged;
    //        VisibleChanged += (s, e) =>
    //        {
    //            _isStop = !Visible;
    //            if (Visible)
    //            {
    //                StartAnimation();
    //            }
    //        };
    //    }

    //    private void UCRollText_SizeChanged(object sender, EventArgs e)
    //    {
    //        if (rectText != Rectangle.Empty)
    //        {
    //            rectText.Y = (this.Height - rectText.Height) / 2 + 1;
    //        }
    //    }

    //    private void UCRollText_Load(object sender, EventArgs e)
    //    {
    //        if (_RollStyle == RollStyle.LeftToRight)
    //        {
    //            m_intdirection = 1;
    //            if (rectText != Rectangle.Empty)
    //            {
    //                rectText.X = -1 * rectText.Width - 1;
    //            }
    //        }
    //        else if (_RollStyle == RollStyle.RightToLeft)
    //        {
    //            m_intdirection = -1;
    //            if (rectText != Rectangle.Empty)
    //            {
    //                rectText.X = this.Width + rectText.Width + 1;
    //            }
    //        }
    //        else
    //        {
    //            m_intdirection = 1;
    //            if (rectText != Rectangle.Empty)
    //            {
    //                rectText.X = 0;
    //            }
    //        }
    //        if (rectText != Rectangle.Empty)
    //        {
    //            rectText.Y = (this.Height - rectText.Height) / 2 + 1;
    //        }
    //    }

    //    private async void StartAnimation()
    //    {
    //        if (!_isStop) return;

    //        _isStop = false;
    //        _cts = new CancellationTokenSource();

    //        try
    //        {
    //            await Task.Run(async () =>
    //            {
    //                while (!_isStop && !_isExit)
    //                {
    //                    try
    //                    {
    //                        await Task.Delay(MoveSleepTime, _cts.Token);
    //                        if (!IsHandleCreated || IsDisposed) continue;

    //                        await UpdateTextPositionAsync();
    //                    }
    //                    catch (OperationCanceledException)
    //                    {
    //                        break;
    //                    }
    //                    catch (Exception ex)
    //                    {
    //                        Debug.WriteLine($"Animation error: {ex.Message}");
    //                    }
    //                }
    //            }, _cts.Token);
    //        }
    //        catch (OperationCanceledException) { }
    //    }

    //    private void StopAnimation()
    //    {
    //        _isStop = true;
    //        try
    //        {
    //            _cts?.Cancel();
    //            _cts?.Dispose();
    //            _cts = null;
    //        }
    //        catch { }
    //    }

    //    private async Task UpdateTextPositionAsync()
    //    {
    //        if (_rectText == Rectangle.Empty) return;
    //        if (_rollStyle == RollStyle.BackAndForth && _rectText.Width >= Width) return;

    //        await _updateLock.WaitAsync();
    //        try
    //        {
    //            // 使用 Invoke 方式
    //            if (InvokeRequired)
    //            {
    //                Invoke((MethodInvoker)delegate
    //                {
    //                    UpdateTextPosition();
    //                });
    //            }
    //            else
    //            {
    //                UpdateTextPosition();
    //            }
    //        }
    //        finally
    //        {
    //            _updateLock.Release();
    //        }
    //    }


    //    private void UpdateTextPosition()
    //    {
    //        _rectText.X += DEFAULT_MOVE_STEP * _moveDirection;

    //        switch (_rollStyle)
    //        {
    //            case RollStyle.BackAndForth:
    //                if (_rectText.X <= 0)
    //                    _moveDirection = 1;
    //                else if (_rectText.Right >= Width)
    //                    _moveDirection = -1;
    //                break;

    //            case RollStyle.LeftToRight:
    //                if (_rectText.X > Width)
    //                    _rectText.X = -1 * _rectText.Width - 1;
    //                break;

    //            case RollStyle.RightToLeft:
    //                if (_rectText.Right < 0)
    //                    _rectText.X = Width + _rectText.Width + 1;
    //                break;
    //        }

    //        Invalidate(true);
    //    }

    //    private void UpdateTextRectangle()
    //    {
    //        if (string.IsNullOrEmpty(Text)) return;

    //        using (var g = CreateGraphics())
    //        {
    //            var size = g.MeasureString(Text, Font);
    //            _rectText = new Rectangle(
    //                _isChangeReset ? 0 : _rectText.X,
    //                (Height - (int)size.Height) / 2 + 1,
    //                (int)size.Width,
    //                (int)size.Height
    //            );
    //        }
    //    }

    //    private void ResetTextPosition()
    //    {
    //        if (_rectText == Rectangle.Empty) return;

    //        switch (_rollStyle)
    //        {
    //            case RollStyle.LeftToRight:
    //                _rectText.X = -1 * _rectText.Width - 1;
    //                break;
    //            case RollStyle.RightToLeft:
    //                _rectText.X = Width + _rectText.Width + 1;
    //                break;
    //            default:
    //                _rectText.X = 0;
    //                break;
    //        }
    //    }

    //    protected override void OnPaint(PaintEventArgs e)
    //    {
    //        base.OnPaint(e);
    //        if (_rectText != Rectangle.Empty)
    //        {
    //            e.Graphics.SetGDIHigh();
    //            using (var brush = new SolidBrush(ForeColor))
    //            {
    //                e.Graphics.DrawString(Text, Font, brush, _rectText.Location);
    //            }
    //        }
    //    }


    //}

    public partial class UCRollText : UserControl
    {
        private Rectangle _rectText;
        private int _moveDirection = 1;
        private const int DEFAULT_MOVE_STEP = 2; // 减小步长，使滚动更平滑
        private const int DEFAULT_SLEEP_TIME = 20; // 减小刷新间隔，提高流畅度

        private readonly SemaphoreSlim _updateLock = new SemaphoreSlim(1, 1);
        private CancellationTokenSource _cts;
        private volatile bool _isStop = true;

        #region Properties

        public override Font Font
        {
            get => base.Font;
            set
            {
                base.Font = value;
                UpdateTextRectangle();
            }
        }

        public override string Text
        {
            get => base.Text;
            set
            {
                base.Text = value;
                UpdateTextRectangle();
            }
        }

        private RollStyle _rollStyle = RollStyle.LeftToRight;
        public RollStyle RollStyle
        {
            get => _rollStyle;
            set
            {
                _rollStyle = value;
                _moveDirection = value == RollStyle.RightToLeft ? -1 : 1;
                ResetTextPosition();
            }
        }

        private bool _isChangeReset;
        [Description("文本改变是否重新从边缘运动"), Category("自定义")]
        public bool IsChangeReset
        {
            get => _isChangeReset;
            set => _isChangeReset = value;
        }

        private bool _isExit;
        [Description("是否退出"), Category("自定义")]
        public bool IsExit
        {
            get => _isExit;
            set
            {
                _isExit = value;
                if (value) StopAnimation();
            }
        }

        private int _moveSleepTime = DEFAULT_SLEEP_TIME;
        [Description("每次滚动间隔时间，越小速度越快"), Category("自定义")]
        public int MoveSleepTime
        {
            get => _moveSleepTime;
            set => _moveSleepTime = value > 0 ? value : DEFAULT_SLEEP_TIME;
        }

        #endregion

        public UCRollText()
        {
            InitializeControl();
            InitializeEvents();
            StartAnimation();
        }

        private void InitializeControl()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint |
                    ControlStyles.DoubleBuffer |
                    ControlStyles.ResizeRedraw |
                    ControlStyles.Selectable |
                    ControlStyles.SupportsTransparentBackColor |
                    ControlStyles.UserPaint, true);

            DoubleBuffered = true; // 启用双缓冲，减少闪烁
            Size = new Size(450, 30);
            Text = "滚动文字";
            ForeColor = Color.FromArgb(255, 77, 59);
        }

        private void InitializeEvents()
        {
            Load += UCRollText_Load;
            SizeChanged += UCRollText_SizeChanged;
            VisibleChanged += (s, e) =>
            {
                _isStop = !Visible;
                if (Visible) StartAnimation();
            };
        }

        private void UCRollText_SizeChanged(object sender, EventArgs e)
        {
            if (_rectText != Rectangle.Empty)
            {
                _rectText.Y = (Height - _rectText.Height) / 2 + 1;
            }
        }

        private void UCRollText_Load(object sender, EventArgs e)
        {
            ResetTextPosition();
        }

        private async void StartAnimation()
        {
            if (!_isStop) return;

            _isStop = false;
            _cts = new CancellationTokenSource();

            try
            {
                await Task.Run(async () =>
                {
                    var stopwatch = new Stopwatch();
                    stopwatch.Start();

                    while (!_isStop && !_isExit)
                    {
                        try
                        {
                            var elapsed = stopwatch.ElapsedMilliseconds;
                            stopwatch.Restart();

                            await Task.Delay(MoveSleepTime, _cts.Token);
                            if (!IsHandleCreated || IsDisposed) continue;

                            await UpdateTextPositionAsync(elapsed);
                        }
                        catch (OperationCanceledException)
                        {
                            break;
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine($"Animation error: {ex.Message}");
                        }
                    }
                }, _cts.Token);
            }
            catch (OperationCanceledException) { }
        }

        private void StopAnimation()
        {
            _isStop = true;
            _cts?.Cancel();
            _cts?.Dispose();
            _cts = null;
        }

        private async Task UpdateTextPositionAsync(long elapsedMilliseconds)
        {
            if (_rectText == Rectangle.Empty) return;
            if (_rollStyle == RollStyle.BackAndForth && _rectText.Width >= Width) return;

            await _updateLock.WaitAsync();
            try
            {
                await Task.Run(() =>
                {
                    if (InvokeRequired)
                    {
                        Invoke((MethodInvoker)(() => UpdateTextPosition(elapsedMilliseconds)));
                    }
                    else
                    {
                        UpdateTextPosition(elapsedMilliseconds);
                    }
                });
            }
            finally
            {
                _updateLock.Release();
            }
        }

        private void UpdateTextPosition(long elapsedMilliseconds)
        {
            // 根据时间调整滚动步长，确保动画平滑
            int step = (int)(DEFAULT_MOVE_STEP * (elapsedMilliseconds / (double)MoveSleepTime));
            _rectText.X += step * _moveDirection;

            switch (_rollStyle)
            {
                case RollStyle.BackAndForth:
                    if (_rectText.X <= 0)
                        _moveDirection = 1;
                    else if (_rectText.Right >= Width)
                        _moveDirection = -1;
                    break;

                case RollStyle.LeftToRight:
                    if (_rectText.X > Width)
                        _rectText.X = -_rectText.Width - 1;
                    break;

                case RollStyle.RightToLeft:
                    if (_rectText.Right < 0)
                        _rectText.X = Width + _rectText.Width + 1;
                    break;
            }

            Invalidate();
        }

        private void UpdateTextRectangle()
        {
            if (string.IsNullOrEmpty(Text)) return;

            using (var g = CreateGraphics())
            {
                var size = g.MeasureString(Text, Font);
                _rectText = new Rectangle(
                    _isChangeReset ? 0 : _rectText.X,
                    (Height - (int)size.Height) / 2 + 1,
                    (int)size.Width,
                    (int)size.Height
                );
            }
        }

        private void ResetTextPosition()
        {
            if (_rectText == Rectangle.Empty) return;

            switch (_rollStyle)
            {
                case RollStyle.LeftToRight:
                    _rectText.X = -_rectText.Width - 1;
                    break;
                case RollStyle.RightToLeft:
                    _rectText.X = Width + _rectText.Width + 1;
                    break;
                default:
                    _rectText.X = 0;
                    break;
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (_rectText != Rectangle.Empty)
            {
                e.Graphics.SetGDIHigh();
                using (var brush = new SolidBrush(ForeColor))
                {
                    e.Graphics.DrawString(Text, Font, brush, _rectText.Location);
                }
            }
        }
    }

    public enum RollStyle
    {
        LeftToRight,
        RightToLeft,
        BackAndForth
    }

}
